package com.imooc.utils;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.facebody.model.v20191230.CompareFaceRequest;
import com.aliyuncs.facebody.model.v20191230.CompareFaceResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.utils.Base64Helper;
import com.google.gson.Gson;
import com.imooc.exception.GraceException;
import com.imooc.grace.result.ResponseStatusEnum;
import com.imooc.utils.extend.AliyunResource;
import org.apache.tomcat.util.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.SimpleTimeZone;

@Component
public class FaceVerifyUtils {

    final static Logger logger = LoggerFactory.getLogger(FaceVerifyUtils.class);

    @Autowired
    private AliyunResource aliyunResource;

    private static final String gateway = "https://dtplus-cn-shanghai.data.aliyuncs.com/face/verify";

    /*
     * 计算MD5+BASE64
     */
    public static String MD5Base64(String s) {
        if (s == null)
            return null;
        String encodeStr = "";
        byte[] utfBytes = s.getBytes();
        MessageDigest mdTemp;
        try {
            mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(utfBytes);
            byte[] md5Bytes = mdTemp.digest();
            Base64Helper b64Encoder = new Base64Helper();
            encodeStr = b64Encoder.encode(md5Bytes);
        } catch (Exception e) {
            throw new Error("Failed to generate MD5 : " + e.getMessage());
        }
        return encodeStr;
    }

    /*
     * 计算 HMAC-SHA1
     */
    public static String HMACSha1(String data, String key) {
        String result;
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(data.getBytes());
            result = (new Base64Helper()).encode(rawHmac);
        } catch (Exception e) {
            throw new Error("Failed to generate HMAC : " + e.getMessage());
        }
        return result;
    }

    /*
     * 等同于javaScript中的 new Date().toUTCString();
     */
    public static String toGMTString(Date date) {
        SimpleDateFormat df = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z", Locale.UK);
        df.setTimeZone(new SimpleTimeZone(0, "GMT"));
        return df.format(date);
    }


    //如果发送的是转换为base64编码后后面加请求参数type为1，如果请求的是图片的url则不用加type参数。
    public String sendPostVerifyFace(String face1, String face2) throws Exception {
        DefaultProfile profile = DefaultProfile.getProfile("cn-shanghai", aliyunResource.getAccessKeyID(), aliyunResource.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);
        CompareFaceRequest request = new CompareFaceRequest();
        request.setImageDataA(face1);
        request.setImageDataB(face2);
        request.setQualityScoreThreshold(60.0F);
        String result = null;
        try {
            CompareFaceResponse response = client.getAcsResponse(request);
            result = new Gson().toJson(response);
            System.out.println("result = " + result);
        }
        catch (ServerException e) {
            e.printStackTrace();
            GraceException.display(ResponseStatusEnum.SYSTEM_ERROR);
        } catch (ClientException e) {
            System.out.println("ErrCode:" + e.getErrCode() + ", ErrMsg:" + e.getErrMsg() + ", RequestId:" + e.getRequestId());
            GraceException.display(ResponseStatusEnum.FACE_VERIFY_TYPE_ERROR);
        }
        return result;
    }

    /**
     * @param face1
     * @param face2
     * @param targetConfidence 目标可信度，自定义阈值
     * @return
     */
    public boolean faceVerify(String face1, String face2, float targetConfidence) {

        String response = null;
        try {
            response = sendPostVerifyFace(face1, face2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (response == null) {
            return false;
        }
        CompareFaceResponse compareFaceResponse = JsonUtils.jsonToPojo(response, CompareFaceResponse.class);
        Float responseConfidence = compareFaceResponse.getData().getConfidence();
        logger.info("人脸对比结果：{}", responseConfidence);
        if (responseConfidence > targetConfidence) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 将图片转换为Base64
     * 将base64编码字符串解码成img图片
     *
     * @param imgUrl
     * @return
     */
    public String getImgBase64(String imgUrl) {
        ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            // 创建URL
            URL url = new URL(imgUrl);
            byte[] by = new byte[1024];
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            InputStream is = conn.getInputStream();
            // 将内容放到内存中
            int len = -1;
            while ((len = is.read(by)) != -1) {
                data.write(by, 0, len);
            }
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 对字节数组Base64编码
        return Base64.encodeBase64String(data.toByteArray());
    }

//    public static void main(String[] args) {
//        String face3 = "http://122.152.205.72:88/group1/M00/00/05/CpoxxF5MvvGAfnLXAAIHiv37wNk363.jpg";
//        String face4 = "http://122.152.205.72:88/group1/M00/00/05/CpoxxF5Mv3yAH74mAACOiTd9pO4462.jpg";
//
//        boolean result = new FaceVerifyUtils().faceVerify(FaceVerifyType.IMAGE_URL.type, face3, face4, 60);
//
//        logger.info("人脸对比是否成功：{}", result);
//    }

}

